package com.ym.medical.service.impl;

import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import com.ym.common.utils.CalcUtil;

import com.ym.core.exception.BusinessException;
import com.ym.core.utils.DateKit;
import com.ym.core.utils.tkmybatis.BaseSVImpl;

import com.ym.medical.dao.SysAuditDao;
import com.ym.medical.domain.entity.ConsumeDetailsEntity;
import com.ym.medical.domain.entity.SysAuditEntity;
import com.ym.medical.domain.entity.SysDictEntity;
import com.ym.medical.domain.entity.SysDrawEntity;
import com.ym.medical.domain.param.ConsumeDetailsParam;
import com.ym.medical.domain.param.PlatformAccountExampleParam;
import com.ym.medical.domain.param.SysAuditParam;
import com.ym.medical.domain.vo.SysAuditVo;
import com.ym.medical.domain.vo.TdDetailSummaryVO;
import com.ym.medical.enums.*;
import com.ym.medical.service.*;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * ComputerName:LAPTOP-I6GKDIFQ
 * Author:admin
 * Date: 2019-08-17
 * Time: 11:12:04
 * 月初出账，月底打款服务实现类
 */
@Service
@Transactional( rollbackFor = Exception.class)
public class SysAuditSVImpl extends BaseSVImpl<SysAuditEntity, SysAuditDao> implements ISysAuditSV {

    private static final Logger LOGGER = LoggerFactory.getLogger(SysAuditSVImpl.class);

    @Autowired
    private IConsumeDetailsSV consumeDetailsSV;

    @Autowired
    private ISysDrawSV sysDrawSV;

    @Autowired
    private ISysCodeRuleSV iSysCodeRuleSV;

    @Autowired
    private IPlatformTradeDetailSV platformTradeDetailSV;

    @Autowired
    private ISysDictSV sysDictSV;

    @Override
    public TdDetailSummaryVO tdDetailSummary(Date startTime, Date endTime) {
        return mapper.tdDetailSummary(startTime,endTime);
    }
    @Override
    public PageInfo<SysAuditParam> listPageDocIncomeRecord(PlatformAccountExampleParam platformAccountExampleParam, int pageNo, int limit) {
        PageHelper.startPage(pageNo,limit);
        return new PageInfo<>( listDocIncomeRecord(platformAccountExampleParam));
    }
    @Override
    public List<SysAuditParam> listDocIncomeRecord(PlatformAccountExampleParam platformAccountExampleParam) {
        List<SysAuditParam> sysAuditModels = mapper.listDocIncomeRecord(platformAccountExampleParam);
        if(!sysAuditModels.isEmpty()){
            for (SysAuditParam sysAuditModel : sysAuditModels) {
                    //1.查询每个医生对应的消费明细主键 方便后期往交易明细中保存系统出账主键
                platformAccountExampleParam.setAccId(sysAuditModel.getAccountId());
                    sysAuditModel.setConsumeDetailIds(mapper.listDocIncomeDetailId(platformAccountExampleParam));

                    //2. 计算医生的实际收入
                    if(platformAccountExampleParam.getStartTime() != null && platformAccountExampleParam.getEndTime() != null){
                        sysAuditModel.setTimePeroid(DateUtil.date(platformAccountExampleParam.getStartTime()).toString()+"-"+DateKit.parseDateToStr(DateKit.YYYY_MM_DD_HH_MM_SS,platformAccountExampleParam.getEndTime()));
                        sysAuditModel.setStartTime(platformAccountExampleParam.getStartTime());
                        sysAuditModel.setEndTime(platformAccountExampleParam.getEndTime());
                    }

                    BigDecimal amount = sysAuditModel.getAmount();     //提现总金额
                    BigDecimal platform = null;
                    BigDecimal reflect = null;
                    BigDecimal individual = null;
                    List<SysDictEntity> sysDicts = sysDictSV.getCodeAndDesc(DividedRateEnum.class);
                    for (SysDictEntity sysDict : sysDicts) {
                        String itemCode = sysDict.getItemCode();
                        String itemDesc = sysDict.getItemDesc();
                        if(DividedRateEnum.PLATFORM_YIELD_RATE.getKey().equals(itemCode)){
                             platform = CalcUtil.mul(Double.valueOf(itemDesc), amount).decimalValue();
                            sysAuditModel.setDrawAmount(platform);    //平台抽成金额
                        }else if(DividedRateEnum.REFLECT_RATE.getKey().equals(itemCode)){
                             reflect = CalcUtil.mul(Double.valueOf(itemDesc), amount).decimalValue();
                            sysAuditModel.setWithdrawFee(reflect);  //提现手续费
                        }else if(DividedRateEnum.INDIVIDUAL_INCOME_TAX_RATE.getKey().equals(itemCode)){
                             individual = CalcUtil.mul(Double.valueOf(itemDesc), amount).decimalValue();
                            sysAuditModel.setIncomeTax(individual);   //个人所得税
                        }

                    }
                BigDecimal realityStatement = CalcUtil.sub(amount,platform).sub(reflect).sub(individual).decimalValue();
                sysAuditModel.setActIncomeAmount(realityStatement);  //实际到账金额
                    //3. 医生的抽成明细
                    List<SysDrawEntity> sysDraws = new ArrayList<SysDrawEntity>();
                    SysDrawEntity toMindDraw = new SysDrawEntity();
                    SysDrawEntity inquiryDraw = new SysDrawEntity();
                platformAccountExampleParam.setAccId(sysAuditModel.getAccountId());
                    List<ConsumeDetailsEntity> consumeDetailsList = consumeDetailsSV.listDocIncomeRecord(platformAccountExampleParam);
                    if(!consumeDetailsList.isEmpty()){
                        for (ConsumeDetailsEntity consumeDetails : consumeDetailsList) {
                            String tdType = consumeDetails.getTdType();  //交易类型
                            BigDecimal tdAmount = consumeDetails.getTdAmount();  //交易金额
                            BigDecimal percent = null;   //抽成费率
                            if(ConsumeDetailsTdTypeEnum.TO_MIND.getKey().equals(tdType)){
                                LOGGER.info("送心意订单抽成 总金额:{}",tdAmount);
                                toMindDraw.setIncomeCode(IncomeItemEnum.TO_MY_MIND.getKey());
                                toMindDraw.setIncomeAmount(tdAmount);
                                //送心意抽成费率
                                percent = new BigDecimal(DividedRateEnum.INQUIRY_RAKE_RATE.getKey());
                                toMindDraw.setDrawPercent(percent);
                                toMindDraw.setDrawAmount(CalcUtil.mul(tdAmount,percent).decimalValue());
                                //实际收入
                                toMindDraw.setActIncomeAmount(CalcUtil.sub(tdAmount,CalcUtil.mul(tdAmount,percent).decimalValue(4)).decimalValue());
                                toMindDraw.setRemark("送心意抽成: "+tdAmount+"-("+tdAmount+"*"+percent+")="+CalcUtil.sub(tdAmount,CalcUtil.mul(tdAmount,percent).decimalValue()).decimalValue());
                            }else {
                                LOGGER.info("问诊订单抽成 总金额:{}",tdAmount);
                                inquiryDraw.setIncomeCode(IncomeItemEnum.PHYSICIAN_VISITS.getKey());
                                inquiryDraw.setIncomeAmount(tdAmount);
                                //问诊抽成费率
                                percent = new BigDecimal(DividedRateEnum.MIND_RAKE_RATE.getKey());
                                inquiryDraw.setDrawPercent(percent);
                                inquiryDraw.setDrawAmount(CalcUtil.mul(tdAmount,percent).decimalValue());
                                //实际收入
                                inquiryDraw.setActIncomeAmount(CalcUtil.sub(tdAmount,CalcUtil.mul(tdAmount,percent).decimalValue(4)).decimalValue());
                                inquiryDraw.setRemark("问诊订单抽成: "+tdAmount+"-("+tdAmount+"*"+percent+")="+ CalcUtil.sub(tdAmount,CalcUtil.mul(tdAmount,percent).decimalValue()).decimalValue());
                            }
                        }
                    }
                sysDraws.add(inquiryDraw);
                sysDraws.add(toMindDraw);
                sysAuditModel.setSysDraws(sysDraws);
            }
        }
       return sysAuditModels;
    }

    /**
     * 系统自动出账
     */
    @Override
    public void autoInsertSysAudit() {
        //获取上月月的消费明细
        PlatformAccountExampleParam exampleVO = new PlatformAccountExampleParam();
        String yearMonth = DateKit.getYearMonth();
        String[] lastTime = yearMonth.split("-");
        Integer lastYear = Integer.valueOf(lastTime[0]);
        Integer lastMonth = Integer.valueOf(lastTime[1]);
        exampleVO.setStartTime(DateKit.getFirstDayOfMonth(lastYear,lastMonth));
        exampleVO.setEndTime(DateKit.getLastDayOfMonth(lastYear,lastMonth));
        List<SysAuditParam> sysAuditModels = listDocIncomeRecord(exampleVO);
        if(sysAuditModels.isEmpty()){
            LOGGER.info("没有可出账的账单!");
            return;
        }
        //出账
        artificialSysAudit(null,sysAuditModels);
    }


    @Override
    public void artificialSysAudit(Long sysId, List<SysAuditParam> sysAuditModelList) {
        if(sysAuditModelList.isEmpty()){
            throw new BusinessException("至少选择一个出账记录");
        }

        for (SysAuditParam sysAuditModel : sysAuditModelList) {
            List<Long> consumeDetailIds = sysAuditModel.getConsumeDetailIds();

            //1. 修改出账记录
            sysAuditModel.setSettlementStatus(SettlementStatusEnum.ALREADY_ENTER_AN_ITEM_OF_EXPENDITURE_IN_THE_ACCOUNTS.getKey());
            sysAuditModel.setBillingTime(new Date());
            sysAuditModel.setSettlementPerson(sysId);
            sysAuditModel.setTdNo(iSysCodeRuleSV.createCode(CodeRuleEnum.TRANSACTION_SERIAL_NUMBER));
            if(sysAuditModel.getId() != null){
                mapper.updateByPrimaryKeySelective(sysAuditModel.covert());
            }else {
                mapper.insertSelective(sysAuditModel.covert());
            }
            //2. 保存抽成明细记录
            List<SysDrawEntity> sysDraws = sysAuditModel.getSysDraws();
            if(!sysDraws.isEmpty()){
                for (SysDrawEntity sysDraw : sysDraws) {
                    if(sysDraw != null && (StringUtils.isNotBlank(sysDraw.getIncomeCode()))){
                        sysDraw.setAuditId(sysAuditModel.getId());
                        sysDraw.setCreated(sysId);
                        sysDraw.setCreateTime(new Date());
                        sysDraw.setUpdated(sysId);
                        sysDraw.setUpdateTime(new Date());
                        if(sysDraw.getId() != null){
                            sysDrawSV.updateById(sysDraw);
                        }else {
                            sysDrawSV.insert(sysDraw);
                        }
                    }
                }
            }
            //3. 修改消费明细表中系统出账主键
            ConsumeDetailsParam consumeDetailsModel = new ConsumeDetailsParam();
            consumeDetailsModel.setSysAuditId(sysAuditModel.getId());
            consumeDetailsSV.updateBatchById(consumeDetailsModel,consumeDetailIds);
        }
    }

    @Override
    public PageInfo<SysAuditVo> listPageSysAudit(PlatformAccountExampleParam platformAccountExampleParam, int pageNo, int limit) {
        PageHelper.startPage(pageNo,limit);
        return new PageInfo<>(listSysAudit(platformAccountExampleParam));
    }

    @Override
    public int updateBatchById(SysAuditParam sysAuditModel, Long[] auditIds) {
        return mapper.updateBatchById(sysAuditModel,auditIds);
    }

    @Override
    public List<SysAuditVo> listSysAudit(PlatformAccountExampleParam platformAccountExampleVO) {
        return mapper.listSysAudit(platformAccountExampleVO);
    }

    /**
     * 出账单作废
     * @param auditIds
     */
    @Override
    public void cancelSysAudit(Long[] auditIds) {
        //1. 修改状态为 已作废
        SysAuditParam sysAuditModel = new SysAuditParam();
        sysAuditModel.setSettlementStatus(SettlementStatusEnum.THE_CANCELLATION.getKey());
        mapper.updateBatchById(sysAuditModel,auditIds);

        //2. 将对应的消费明细表中系统出账主键清空
        consumeDetailsSV.clearSysAuditId(auditIds);

    }

    /**
     * 出账结算
     * @param auditIds
     * @param sysUserId
     * @return
     */
    @Override
    public int settleSysAudit(Long[] auditIds, Long sysUserId) {
        int rows = 0;
        List<SysAuditEntity> sysAudits = this.selectList(SelectWhere().andIn(SysAuditEntity::getId,auditIds).end());
        if(!sysAudits.isEmpty()){
            for (SysAuditEntity sysAudit : sysAudits) {
                sysAudit.setSettlementStatus(SettlementStatusEnum.HAS_BEEN_SETTLED.getKey());
                sysAudit.setModifierId(sysUserId);
                sysAudit.setModifyTime(new Date());

                //1. 修改系统出账表
                 rows = mapper.updateByPrimaryKeySelective(sysAudit);

                //2. 修改平台账户余额 增加平台账户交易明细
                platformTradeDetailSV.insertPlaformTradeDetail(ComputeWayEnum.TO_REDUCE.getKey(),sysAudit.getAmount(),sysAudit.getId(),
                                        "系统出账", TransactionDetailsTdTypeEnum.ENTER_AN_ITEM_OF_EXPENDITURE_IN_THE_ACCOUNTS.getKey(), CashFlowEnum.EXPEND.getKey());
            }
        }
        return rows;
    }
}
